package main

import (
	"reflect"
	"fmt"
)

type Student struct {
	Name  string `json:"student_name"`
	Age   int
	Score float32
}

func (s Student) Print() {
	fmt.Println(s)
}

func (s Student) Set(name string, age int, score float32) {
	s.Name = name
	s.Age = age
	s.Score = score
}

func TestStruct(a interface{}) {
	val := reflect.ValueOf(a)
	typ := reflect.TypeOf(a)
	kd := val.Kind()

	if kd != reflect.Ptr && val.Elem().Kind() == reflect.Struct {
		fmt.Println("expect struct")
		return
	}

	num := val.Elem().NumField()
	val.Elem().Field(0).SetString("stu1000")

	fmt.Printf("struct has %d fields\n", num)
	for i := 0; i < num; i++ {
		fmt.Printf("%d %v\n", i, val.Elem().Field(i).Kind())
	}

	numOfMethod := val.Elem().NumMethod()
	fmt.Printf("struct has %d methods\n", numOfMethod)

	tag := typ.Elem().Field(0).Tag.Get("json")
	fmt.Printf("tag=%s\n", tag)

	var param []reflect.Value
	val.Method(0).Call(param)
}

func main() {
	var a = Student{
		Name:  "stu01",
		Age:   18,
		Score: 88.5,
	}

	TestStruct(&a)
}
